<!DOCTYPE html>
<!-- saved from url=(0049)https://www.cnblogs.com/yixuanhan/p/12593724.html -->
<html lang="zh-cn"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="referrer" content="origin">
    <meta property="og:description" content="本文是一篇偏实战的博客，完整项目下载地址：https://gitee.com/hanyixuan_net/donet-core 我们将演示如何在ASP.NET CORE3.1 API中使用JWT(JS">
    <meta http-equiv="Cache-Control" content="no-transform">
    <meta http-equiv="Cache-Control" content="no-siteapp">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园</title>
    
    <link rel="stylesheet" href="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/blog-common.min.css">
    <link id="MainCss" rel="stylesheet" href="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/bundle-buildtowin.min.css">
    <link type="text/css" rel="stylesheet" href="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/custom.css">
    <link id="mobile-style" media="only screen and (max-width: 767px)" type="text/css" rel="stylesheet" href="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/bundle-buildtowin-mobile.min.css">
    
    <link type="application/rss+xml" rel="alternate" href="https://www.cnblogs.com/yixuanhan/rss">
    <link type="application/rsd+xml" rel="EditURI" href="https://www.cnblogs.com/yixuanhan/rsd.xml">
    <link type="application/wlwmanifest+xml" rel="wlwmanifest" href="https://www.cnblogs.com/yixuanhan/wlwmanifest.xml">
    <script async="" src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/analytics.js.下载"></script><script type="text/javascript" src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/encoder.js.下载"></script><script src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/jquery-2.2.0.min.js.下载"></script>
    <script src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/blog-common.min.js.下载"></script>
    <script>
        var currentBlogId = 195723;
        var currentBlogApp = 'yixuanhan';
        var cb_enable_mathjax = false;
        var isLogined = false;
        var skinName = 'BuildtoWin';
    </script>
    
    
    
<link rel="preload" href="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/f.txt" as="script"><script type="text/javascript" src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/f.txt"></script><script src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/pubads_impl_2020042302.js.下载" async=""></script><link rel="prefetch" href="https://tpc.googlesyndication.com/safeframe/1-0-37/html/container.html"></head>
<body>
    <a name="top"></a>
    
    
<!--done-->
<div id="home">
<div id="header">
	<div id="blogTitle">
        <a id="lnkBlogLogo" href="https://www.cnblogs.com/yixuanhan/"><img id="blogLogo" src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/logo.gif" alt="返回主页"></a>		
		
<!--done-->
<h1><a id="Header1_HeaderTitle" class="headermaintitle HeaderMainTitle" href="https://www.cnblogs.com/yixuanhan/">yixuan.han</a>
</h1>
<h2>

</h2>




		
	</div><!--end: blogTitle 博客的标题和副标题 -->
	<div id="navigator">
		
<ul id="navList">
<li><a id="blog_nav_sitehome" class="menu" href="https://www.cnblogs.com/">
博客园</a>
</li>
<li>
<a id="blog_nav_myhome" class="menu" href="https://www.cnblogs.com/yixuanhan/">
首页</a>
</li>
<li>

<a id="blog_nav_newpost" class="menu" href="https://i.cnblogs.com/EditPosts.aspx?opt=1">
新随笔</a>
</li>
<li>
<a id="blog_nav_contact" class="menu" href="https://msg.cnblogs.com/send/yixuan.han">
联系</a></li>
<li>
<a id="blog_nav_rss" class="menu" href="https://www.cnblogs.com/yixuanhan/rss/">
订阅</a>
<!--<partial name="./Shared/_XmlLink.cshtml" model="Model" /></li>--></li>
<li>
<a id="blog_nav_admin" class="menu" href="https://i.cnblogs.com/">
管理</a>
</li>
</ul>


		<div class="blogStats">
			
			<span id="stats_post_count">随笔 - 
43&nbsp; </span>
<span id="stats_article_count">文章 - 
6&nbsp; </span>
<span id="stats-comment_count">评论 - 
20</span>

			
		</div><!--end: blogStats -->
	</div><!--end: navigator 博客导航栏 -->
</div><!--end: header 头部 -->

<div id="main">
	<div id="mainContent">
	<div class="forFlow">
		<div id="post_detail">
    <!--done-->
    <div id="topics">
        <div class="post">
            <h1 class="postTitle">
                
<a id="cb_post_title_url" class="postTitle2" href="https://www.cnblogs.com/yixuanhan/p/12593724.html">JWT在ASP.NET Core3.1的应用</a>

            </h1>
            <div class="clear"></div>
            <div class="postBody">
                
<div id="cnblogs_post_body" class="blogpost-body "><a name="_labelTop"></a><div id="navCategory" style="color:#152e97;"><p style="font-size:18px;"><b>目录</b></p><ul><li><a href="https://www.cnblogs.com/yixuanhan/p/12593724.html#_label0">开发ASP.NET CORE 3.1应用程序所需的工具</a></li><li><a href="https://www.cnblogs.com/yixuanhan/p/12593724.html#_label1">在本地运行示例 ASP.NET Core JWT身份验证API</a></li><li><a href="https://www.cnblogs.com/yixuanhan/p/12593724.html#_label2">使用Postman测试ASP.NET Core API</a></li><li><a href="https://www.cnblogs.com/yixuanhan/p/12593724.html#_label3">ASP.NET Core JWT API项目结构</a></li></ul></div><p>&nbsp;</p><hr style="height:1px;border:none;border-top:1px dashed #0066CC;">
    <p><span style="font-family: &#39;Microsoft YaHei&#39;;">&nbsp;</span></p>
<p><span style="font-family: &#39;Microsoft YaHei&#39;;">本文是一篇偏实战的博客，完整项目下载地址：<a href="https://gitee.com/hanyixuan_net/donet-core" target="_blank">https://gitee.com/hanyixuan_net/donet-core</a></span></p>
<p><span style="font-family: &#39;Microsoft YaHei&#39;;">我们将演示如何在ASP.NET CORE3.1 API中使用JWT(JSON Web Token)身份认证。</span></p>
<p><span style="font-family: &#39;Microsoft YaHei&#39;;">本次示例有两个路由,以演示如何使用JWT进行身份验证和使用JWT访问受限路由：</span></p>
<p><span style="font-family: &#39;Microsoft YaHei&#39;;"><span style="color: #ff6600;">/user/authenticate&nbsp;</span> -接受HTTP POST请求（正文中包含用户名和密码）的公共路由。如果用户名和密码正确，则返回JWT身份验证Token和用户详细信息。</span></p>
<p><span style="font-family: &#39;Microsoft YaHei&#39;;"><span style="color: #ff6600;">/user&nbsp;</span>&nbsp; -如果HTTP授权标头包含有效的JWT Token，则该安全路由接受HTTP GET 请求并返回应用程序中的所有用户的列表；如果没有令牌或者令牌无效，则返回401未经授权的响应。</span></p>
<h2 id="autoid-0-0-0"><span style="font-family: &#39;Microsoft YaHei&#39;;">开发ASP.NET CORE 3.1应用程序所需的工具</span></h2>
<p><span style="font-family: &#39;Microsoft YaHei&#39;;">本地开发ASP.NET CORE应用程序需要的下载和安装的工具如下：</span></p>
<p><span style="font-family: &#39;Microsoft YaHei&#39;;"><span style="color: #ff6600;"><a href="https://www.microsoft.com/net/download/core" target="_blank"><span style="color: #ff6600;">.NET Core SDK</span></a>&nbsp;</span>报告.NET Core运行时和命令行工具</span></p>
<p><span style="font-family: &#39;Microsoft YaHei&#39;;"><span style="color: #ff6600;"><a href="https://code.visualstudio.com/" target="_blank"><span style="color: #ff6600;">Visual Studio Code</span></a>&nbsp;</span>支持windows mac linux的代码编辑器</span></p>
<h2 id="autoid-1-0-0"><span style="font-family: &#39;Microsoft YaHei&#39;;">在本地运行示例 ASP.NET Core JWT身份验证API</span></h2>
<ol>
<li><span style="font-family: &#39;Microsoft YaHei&#39;;">从码云上下载和克隆代码&nbsp;<a href="https://gitee.com/hanyixuan_net/donet-core" target="_blank">https://gitee.com/hanyixuan_net/donet-core</a></span></li>
<li><span style="font-family: &#39;Microsoft YaHei&#39;;">在项目的根目录（.csproj文件所在的目录）打开命令行运行 dotnet run来启动API。启动之后会看到代码会运行在localhost:1022的地址，可以通过使用Postman进行测试，也可以用单页面应用程序(Angular,React或者Vue)进行调用。</span></li>
</ol>
<h2 id="autoid-2-0-0"><span style="font-family: &#39;Microsoft YaHei&#39;;">使用Postman测试ASP.NET Core API</span></h2>
<p><span style="font-family: &#39;Microsoft YaHei&#39;;">Postman可以用来测试API,墙裂推荐，下载地址：<a href="https://www.getpostman.com/" target="_blank">https://www.getpostman.com/</a>.</span></p>
<p><span style="font-family: &#39;Microsoft YaHei&#39;;">以下是关于如何使用Postman调用api获取JWT令牌来进行身份验证，然后使用JWT令牌发出经过身份认证的请求以从api检索用户列表的说明。</span></p>
<p><span style="font-family: &#39;Microsoft YaHei&#39;;">&nbsp;要使用API通过Postman验证用户并获取JWT令牌，有以下几个步骤：</span></p>
<ol>
<li><span style="font-family: &#39;Microsoft YaHei&#39;;">选择最上面选项卡“+New”，选择“Request”</span></li>
<li><span style="font-family: &#39;Microsoft YaHei&#39;;">将<span lang="EN-US">http请求方法<span lang="EN-US">改为“<span lang="EN-US">Post”</span></span></span></span></li>
<li><span style="font-family: &#39;Microsoft YaHei&#39;;" lang="EN-US"><span lang="EN-US"><span lang="EN-US">在url文本框中输入要请求的本地Url Api：<span style="text-decoration: underline; color: #3366ff;">http://localhost:1022/user/authenticate</span></span></span></span></li>
<li><span style="font-family: &#39;Microsoft YaHei&#39;;">在地址栏下面选择"Body"选项卡，将正文类型单选按钮更改为“Raw”，并将格式下拉框选择器更改为“Json”。</span></li>
<li><span style="font-family: &#39;Microsoft YaHei&#39;;">在“Body”下面的文本框输入包含测试用户名和密码的Json对象</span></li>
<li><span style="font-family: &#39;Microsoft YaHei&#39;;">点击“Send”按钮，应该会收到一个“200 OK”的响应在响应文本中包含了带有JWT令牌的用户详细信息。请复制这个Token，下一步会用它来验证。</span></li>
</ol>
<p><span style="font-family: &#39;Microsoft YaHei&#39;;">这是一张Postman请求之后验证成功并获取到Token之后的图：</span></p>
<p><span style="font-family: &#39;Microsoft YaHei&#39;;"><img src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/665347-20200329171352762-2100193831.png" alt=""></span></p>
<p><span style="font-family: &#39;Microsoft YaHei&#39;;">&nbsp;获取到Token之后，接下来我们将用获取到的Token做认证请求,有以下几步：</span></p>
<ol>
<li><span style="font-family: &#39;Microsoft YaHei&#39;;">选择最上面选项卡“+New”，选择“Request”</span></li>
<li><span style="font-family: &#39;Microsoft YaHei&#39;;">将http请求方法改成“GET”</span></li>
<li><span style="font-family: &#39;Microsoft YaHei&#39;;">在url文本框中输入要请求的本地Url api: http://localhost:1022/user/</span></li>
<li><span style="font-family: &#39;Microsoft YaHei&#39;;">在URL框下面选择“Authorization”，然后将类型Type改为“Bearer Token”，将上一步得到的Token粘贴到Token字段值中。</span></li>
<li><span style="font-family: &#39;Microsoft YaHei&#39;;">点击“Send”按钮，应该会收到“200 OK”的响应，其中包含一个Json数组，Json数组中包含系统中的所有用户信息（示例中仅一个测试用户）</span></li>
</ol>
<p><span style="font-family: &#39;Microsoft YaHei&#39;;">下面是Postman中通过Token获取所有用户的截图：</span></p>
<p><span style="font-family: &#39;Microsoft YaHei&#39;;"><img src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/665347-20200329171913131-122787738.png" alt=""></span></p>
<h2 id="autoid-3-0-0"><span style="font-family: &#39;Microsoft YaHei&#39;;">ASP.NET Core JWT API项目结构</span></h2>
<p><span style="font-family: &#39;Microsoft YaHei&#39;;"><img src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/665347-20200329172054258-841291683.png" alt=""></span></p>
<p><span style="font-family: &#39;Microsoft YaHei&#39;;">&nbsp;下面主要对几个重要的代码文件做一些简要说明</span></p>
<h4 align="left" id="autoid-4-0-0"><span style="color: #ff6600; font-family: &#39;Microsoft YaHei&#39;;">/Controllers/UserController.cs</span></h4>
<p align="left"><span style="font-family: &#39;Microsoft YaHei&#39;;">定义和处理和用户相关的api的所有api的路由，包括身份验证和标准的CRUD操作。在每个路由中，控制器都调用用户服务(UserService)以执行所需要的操作，这使得业务逻辑和数据访问代码完全隔离。</span></p>
<p align="left"><span style="font-family: &#39;Microsoft YaHei&#39;;">UserController使用了[Authorize]属性来保护控制器，但是Authenticate例外，Authenticate使用了[AllowAnonymous]属性覆盖了控制器上的[Authorize]属性来允许公共访问。</span></p>
<div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/copycode.gif" alt="复制代码"></a></span></div>
<pre><span style="font-family: &#39;Microsoft YaHei&#39;;"><span style="color: #008080;"> 1</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> Microsoft.AspNetCore.Mvc;
</span><span style="color: #008080;"> 2</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> Microsoft.AspNetCore.Authorization;
</span><span style="color: #008080;"> 3</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> JwtAuthDemo.IServices;
</span><span style="color: #008080;"> 4</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> System.Linq;
</span><span style="color: #008080;"> 5</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> JwtAuthDemo.Models;
</span><span style="color: #008080;"> 6</span> <span style="color: #0000ff;">namespace</span><span style="color: #000000;"> JwtAuthDemo.Controllers
</span><span style="color: #008080;"> 7</span> <span style="color: #000000;">{
</span><span style="color: #008080;"> 8</span> <span style="color: #000000;">    [Authorize]
</span><span style="color: #008080;"> 9</span> <span style="color: #000000;">    [ApiController]
</span><span style="color: #008080;">10</span>     [Route(<span style="color: #800000;">"</span><span style="color: #800000;">[controller]</span><span style="color: #800000;">"</span><span style="color: #000000;">)]
</span><span style="color: #008080;">11</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> UserController:ControllerBase
</span><span style="color: #008080;">12</span> <span style="color: #000000;">    {
</span><span style="color: #008080;">13</span>         <span style="color: #0000ff;">private</span><span style="color: #000000;"> IUserService _userService;
</span><span style="color: #008080;">14</span>         <span style="color: #0000ff;">public</span><span style="color: #000000;"> UserController(IUserService userService)
</span><span style="color: #008080;">15</span> <span style="color: #000000;">        {
</span><span style="color: #008080;">16</span>           _userService=<span style="color: #000000;">userService;
</span><span style="color: #008080;">17</span> <span style="color: #000000;">        }
</span><span style="color: #008080;">18</span> <span style="color: #000000;">         [AllowAnonymous]
</span><span style="color: #008080;">19</span>         [HttpPost(<span style="color: #800000;">"</span><span style="color: #800000;">authenticate</span><span style="color: #800000;">"</span><span style="color: #000000;">)]
</span><span style="color: #008080;">20</span>         <span style="color: #0000ff;">public</span><span style="color: #000000;"> IActionResult Authenticate([FromBody]AuthenticateModel model)
</span><span style="color: #008080;">21</span> <span style="color: #000000;">        {
</span><span style="color: #008080;">22</span>             <span style="color: #0000ff;">var</span> user=<span style="color: #000000;">_userService.Authenticate(model.UserName,model.Password);
</span><span style="color: #008080;">23</span>             <span style="color: #0000ff;">if</span>(User==<span style="color: #0000ff;">null</span><span style="color: #000000;">)
</span><span style="color: #008080;">24</span> <span style="color: #000000;">            {
</span><span style="color: #008080;">25</span>                 <span style="color: #0000ff;">return</span> BadRequest(<span style="color: #0000ff;">new</span> {message=<span style="color: #800000;">"</span><span style="color: #800000;">用户名或者密码不正确</span><span style="color: #800000;">"</span><span style="color: #000000;">});
</span><span style="color: #008080;">26</span> <span style="color: #000000;">            }
</span><span style="color: #008080;">27</span>             <span style="color: #0000ff;">return</span><span style="color: #000000;"> Ok(user);
</span><span style="color: #008080;">28</span> <span style="color: #000000;">        }
</span><span style="color: #008080;">29</span>         <span style="color: #0000ff;">public</span><span style="color: #000000;"> IActionResult GetAll()
</span><span style="color: #008080;">30</span> <span style="color: #000000;">        {
</span><span style="color: #008080;">31</span>             <span style="color: #0000ff;">var</span> users=<span style="color: #000000;">_userService.GetAll();
</span><span style="color: #008080;">32</span>             <span style="color: #0000ff;">return</span><span style="color: #000000;"> Ok(users);
</span><span style="color: #008080;">33</span> <span style="color: #000000;">        }
</span><span style="color: #008080;">34</span> 
<span style="color: #008080;">35</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">36</span> }</span></pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/copycode.gif" alt="复制代码"></a></span></div></div>
<h4 align="left" id="autoid-4-0-1"><span style="color: #ff6600; font-family: &#39;Microsoft YaHei&#39;;">/Entities/User.cs</span></h4>
<p align="left"><span style="font-family: &#39;Microsoft YaHei&#39;;">实体类用于在应用程序不同部分之间(如服务和控制器)传递数据，也可以用于从控制器操作方法返回HTTP响应数据。但是有时候控制器方法需要返回多种数据类型实体或者其他一些自定义数据，这个是很好就需要在Models文件夹中创建自定义的模型类数据进行响应。</span></p>
<div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/copycode.gif" alt="复制代码"></a></span></div>
<pre><span style="font-family: &#39;Microsoft YaHei&#39;;"><span style="color: #008080;"> 1</span> <span style="color: #0000ff;">namespace</span><span style="color: #000000;"> JwtAuthDemo.Entities
</span><span style="color: #008080;"> 2</span> <span style="color: #000000;">{
</span><span style="color: #008080;"> 3</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> User
</span><span style="color: #008080;"> 4</span> <span style="color: #000000;">    {
</span><span style="color: #008080;"> 5</span>         <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">int</span> Id { <span style="color: #0000ff;">get</span>; <span style="color: #0000ff;">set</span><span style="color: #000000;">; }
</span><span style="color: #008080;"> 6</span>         <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> FirstName{<span style="color: #0000ff;">get</span>;<span style="color: #0000ff;">set</span><span style="color: #000000;">;}
</span><span style="color: #008080;"> 7</span>         <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> LastName{<span style="color: #0000ff;">get</span>;<span style="color: #0000ff;">set</span><span style="color: #000000;">;}
</span><span style="color: #008080;"> 8</span>         <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> UserName{<span style="color: #0000ff;">get</span>;<span style="color: #0000ff;">set</span><span style="color: #000000;">;}
</span><span style="color: #008080;"> 9</span>         <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> Password{<span style="color: #0000ff;">get</span>;<span style="color: #0000ff;">set</span><span style="color: #000000;">;}
</span><span style="color: #008080;">10</span>         <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> Token{<span style="color: #0000ff;">get</span>;<span style="color: #0000ff;">set</span><span style="color: #000000;">;}
</span><span style="color: #008080;">11</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">12</span> }</span></pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/copycode.gif" alt="复制代码"></a></span></div></div>
<h4 align="left" id="autoid-4-0-2"><span style="color: #ff6600; font-family: &#39;Microsoft YaHei&#39;;">&nbsp;/Helper/AppSettings.cs</span></h4>
<p align="left"><span style="font-family: &#39;Microsoft YaHei&#39;;">AppSettings.cs中定义了appsettings.json中的属性，用于通过依赖注入到类中的对象来访问应用程序设置。如用户服务通过注入构造函数中的IOptions&lt;AppSettings&gt; appSettings 对象访问应用程序设置。</span></p>
<p align="left"><span style="font-family: &#39;Microsoft YaHei&#39;;">在Startup.cs的<code>ConfigureServices</code>&nbsp;中完成配置文件sections到类的映射。</span></p>
<div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/copycode.gif" alt="复制代码"></a></span></div>
<pre><span style="font-family: &#39;Microsoft YaHei&#39;;"><span style="color: #008080;">1</span> <span style="color: #0000ff;">namespace</span><span style="color: #000000;"> JwtAuthDemo.Helper
</span><span style="color: #008080;">2</span> <span style="color: #000000;">{
</span><span style="color: #008080;">3</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> AppSettings
</span><span style="color: #008080;">4</span> <span style="color: #000000;">{
</span><span style="color: #008080;">5</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> Secret{<span style="color: #0000ff;">get</span>;<span style="color: #0000ff;">set</span><span style="color: #000000;">;}
</span><span style="color: #008080;">6</span> <span style="color: #000000;">}
</span><span style="color: #008080;">7</span> }</span></pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/copycode.gif" alt="复制代码"></a></span></div></div>
<h4 align="left" id="autoid-4-0-3"><span style="color: #ff6600; font-family: &#39;Microsoft YaHei&#39;;">&nbsp;/Helpers/ExtensionMethods.cs</span></h4>
<p align="left"><span style="font-family: &#39;Microsoft YaHei&#39;;">ExtensionMethods类中一般添加一些有利于程序功能的其他方法。</span></p>
<p align="left"><span style="font-family: &#39;Microsoft YaHei&#39;;">在本例中，添加了两个方法，用于从User实例和<span style="color: #ff6600;">IEnumerable&lt;User&gt;</span>集合中去掉密码。这些方法会在UserService中的<span style="color: #ff6600;">Authenticate</span>和<span style="color: #ff6600;">GetAll</span>方法中调用，以确保返回的对象不包含密码。</span></p>
<div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/copycode.gif" alt="复制代码"></a></span></div>
<pre><span style="font-family: &#39;Microsoft YaHei&#39;;"><span style="color: #008080;"> 1</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> System.Collections.Generic;
</span><span style="color: #008080;"> 2</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> System.Linq;
</span><span style="color: #008080;"> 3</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> JwtAuthDemo.Entities;
</span><span style="color: #008080;"> 4</span> <span style="color: #0000ff;">namespace</span><span style="color: #000000;"> JwtAuthDemo.Helper
</span><span style="color: #008080;"> 5</span> <span style="color: #000000;">{
</span><span style="color: #008080;"> 6</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> ExtensionMethods
</span><span style="color: #008080;"> 7</span> <span style="color: #000000;">    {
</span><span style="color: #008080;"> 8</span>         <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> IEnumerable&lt;User&gt; WithoutPasswords(<span style="color: #0000ff;">this</span> IEnumerable&lt;User&gt;<span style="color: #000000;"> users){
</span><span style="color: #008080;"> 9</span>             <span style="color: #0000ff;">return</span> users.Select(x=&gt;<span style="color: #000000;">x.WithoutPassword());
</span><span style="color: #008080;">10</span> <span style="color: #000000;">        }
</span><span style="color: #008080;">11</span>         <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> User WithoutPassword(<span style="color: #0000ff;">this</span><span style="color: #000000;"> User user){
</span><span style="color: #008080;">12</span>             user.Password=<span style="color: #0000ff;">null</span><span style="color: #000000;">;
</span><span style="color: #008080;">13</span>             <span style="color: #0000ff;">return</span><span style="color: #000000;"> user;
</span><span style="color: #008080;">14</span> <span style="color: #000000;">        }
</span><span style="color: #008080;">15</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">16</span> }</span></pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/copycode.gif" alt="复制代码"></a></span></div></div>
<h4 align="left" id="autoid-4-0-4"><span style="color: #ff6600; font-family: &#39;Microsoft YaHei&#39;;">/Models/AuthenticateModel.cs</span></h4>
<p align="left"><span style="font-family: &#39;Microsoft YaHei&#39;;">AuthenticateModel为api的/users/authenticate 路由定义了传入请求的参数。档次收到对路由HTTP POST请求时，来自正文的数据将绑定到AuthenticateModel的实例，并经过验证传递给方法。</span></p>
<div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/copycode.gif" alt="复制代码"></a></span></div>
<pre><span style="font-family: &#39;Microsoft YaHei&#39;;"><span style="color: #008080;"> 1</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> System.ComponentModel.DataAnnotations;
</span><span style="color: #008080;"> 2</span> <span style="color: #0000ff;">namespace</span><span style="color: #000000;"> JwtAuthDemo.Models
</span><span style="color: #008080;"> 3</span> <span style="color: #000000;">{
</span><span style="color: #008080;"> 4</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> AuthenticateModel
</span><span style="color: #008080;"> 5</span> <span style="color: #000000;">    {
</span><span style="color: #008080;"> 6</span> <span style="color: #000000;">        [Required]
</span><span style="color: #008080;"> 7</span>         <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> UserName{<span style="color: #0000ff;">get</span>;<span style="color: #0000ff;">set</span><span style="color: #000000;">;}
</span><span style="color: #008080;"> 8</span> <span style="color: #000000;">        [Required]
</span><span style="color: #008080;"> 9</span>         <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> Password{<span style="color: #0000ff;">get</span>;<span style="color: #0000ff;">set</span><span style="color: #000000;">;}
</span><span style="color: #008080;">10</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">11</span> }</span></pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/copycode.gif" alt="复制代码"></a></span></div></div>
<h4 align="left" id="autoid-4-0-5"><span style="color: #ff6600; font-family: &#39;Microsoft YaHei&#39;;">/IServices/IUserService.cs</span></h4>
<p align="left"><span style="font-family: &#39;Microsoft YaHei&#39;;">定义用户服务的接口</span></p>
<div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/copycode.gif" alt="复制代码"></a></span></div>
<pre><span style="font-family: &#39;Microsoft YaHei&#39;;"><span style="color: #008080;"> 1</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> System.Collections.Generic;
</span><span style="color: #008080;"> 2</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> JwtAuthDemo.Entities;
</span><span style="color: #008080;"> 3</span> <span style="color: #0000ff;">namespace</span><span style="color: #000000;"> JwtAuthDemo.IServices
</span><span style="color: #008080;"> 4</span> <span style="color: #000000;">{
</span><span style="color: #008080;"> 5</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">interface</span><span style="color: #000000;"> IUserService
</span><span style="color: #008080;"> 6</span> <span style="color: #000000;">    {
</span><span style="color: #008080;"> 7</span>         User Authenticate(<span style="color: #0000ff;">string</span> name,<span style="color: #0000ff;">string</span><span style="color: #000000;"> password);
</span><span style="color: #008080;"> 8</span>         IEnumerable&lt;User&gt;<span style="color: #000000;"> GetAll();
</span><span style="color: #008080;"> 9</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">10</span> }</span></pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/copycode.gif" alt="复制代码"></a></span></div></div>
<h4 align="left" id="autoid-4-0-6"><span style="color: #ff6600; font-family: &#39;Microsoft YaHei&#39;;">/Services/UserService.cs</span></h4>
<p align="left"><span style="font-family: &#39;Microsoft YaHei&#39;;">UserService类中包含一个用于验证用户凭据并返回JWT令牌的方法，以及一个用于获取程序中所有用户的方法。</span></p>
<p align="left"><span style="font-family: &#39;Microsoft YaHei&#39;;">本项目中对用户数组做了硬编码，以使本文更专注与JWT身份验证。在生产环境，建议使用哈希密码将用户存储在数据库中。</span></p>
<p align="left"><span style="font-family: &#39;Microsoft YaHei&#39;;">成功认证后，Authenticate方法使用JwtSecurityTokenHandler类生成JWT（JSON Web令牌），该类生成使用存储在appsettings.json中的密钥进行数字签名的令牌。 JWT令牌返回到客户端应用程序，该客户端应用程序必须将其包含在后续请求的HTTP授权标头中以保护路由<strong>。</strong></span></p>
<div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/copycode.gif" alt="复制代码"></a></span></div>
<pre><span style="font-family: &#39;Microsoft YaHei&#39;;"><span style="color: #008080;"> 1</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> System;
</span><span style="color: #008080;"> 2</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> System.Collections.Generic;
</span><span style="color: #008080;"> 3</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> System.IdentityModel.Tokens.Jwt;
</span><span style="color: #008080;"> 4</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> System.Security.Claims;
</span><span style="color: #008080;"> 5</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> Microsoft.Extensions.Options;
</span><span style="color: #008080;"> 6</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> Microsoft.IdentityModel.Tokens;
</span><span style="color: #008080;"> 7</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> System.Linq;
</span><span style="color: #008080;"> 8</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> System.Text;
</span><span style="color: #008080;"> 9</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> JwtAuthDemo.Entities;
</span><span style="color: #008080;">10</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> JwtAuthDemo.IServices;
</span><span style="color: #008080;">11</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> JwtAuthDemo.Helper;
</span><span style="color: #008080;">12</span> <span style="color: #0000ff;">namespace</span><span style="color: #000000;"> JwtAuthDemo.Services
</span><span style="color: #008080;">13</span> <span style="color: #000000;">{
</span><span style="color: #008080;">14</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> UserService : IUserService
</span><span style="color: #008080;">15</span> <span style="color: #000000;">    {
</span><span style="color: #008080;">16</span>         <span style="color: #008000;">//</span><span style="color: #008000;">这里为了简化流程将用户信息写死，真正在用的时候肯定是从数据库或者其他数据源读取</span>
<span style="color: #008080;">17</span>         <span style="color: #0000ff;">private</span> List&lt;User&gt; _users=<span style="color: #0000ff;">new</span> List&lt;User&gt;
<span style="color: #008080;">18</span> <span style="color: #000000;">        {
</span><span style="color: #008080;">19</span>             <span style="color: #0000ff;">new</span><span style="color: #000000;"> User{
</span><span style="color: #008080;">20</span>                 Id=<span style="color: #800080;">1</span><span style="color: #000000;">,
</span><span style="color: #008080;">21</span>                 FirstName=<span style="color: #800000;">"</span><span style="color: #800000;">yixuan</span><span style="color: #800000;">"</span><span style="color: #000000;">,
</span><span style="color: #008080;">22</span>                 LastName=<span style="color: #800000;">"</span><span style="color: #800000;">han</span><span style="color: #800000;">"</span><span style="color: #000000;">,
</span><span style="color: #008080;">23</span>                 UserName=<span style="color: #800000;">"</span><span style="color: #800000;">hanyixuan</span><span style="color: #800000;">"</span><span style="color: #000000;">,
</span><span style="color: #008080;">24</span>                 Password=<span style="color: #800000;">"</span><span style="color: #800000;">hanyixuan</span><span style="color: #800000;">"</span>
<span style="color: #008080;">25</span>             
<span style="color: #008080;">26</span> <span style="color: #000000;">            }
</span><span style="color: #008080;">27</span> <span style="color: #000000;">        };
</span><span style="color: #008080;">28</span>         <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">readonly</span><span style="color: #000000;"> AppSettings _appSettings;
</span><span style="color: #008080;">29</span>         <span style="color: #0000ff;">public</span> UserService(IOptions&lt;AppSettings&gt;<span style="color: #000000;"> appSettings)
</span><span style="color: #008080;">30</span> <span style="color: #000000;">        {
</span><span style="color: #008080;">31</span>             _appSettings=<span style="color: #000000;">appSettings.Value;
</span><span style="color: #008080;">32</span> <span style="color: #000000;">        }
</span><span style="color: #008080;">33</span>         <span style="color: #0000ff;">public</span> User Authenticate(<span style="color: #0000ff;">string</span> name, <span style="color: #0000ff;">string</span><span style="color: #000000;"> password)
</span><span style="color: #008080;">34</span> <span style="color: #000000;">        {
</span><span style="color: #008080;">35</span>             <span style="color: #0000ff;">var</span> user=_users.SingleOrDefault(x=&gt;x.UserName==name &amp;&amp; x.Password==<span style="color: #000000;">password);
</span><span style="color: #008080;">36</span>            <span style="color: #008000;">//</span><span style="color: #008000;">如果未找到user，则返回null</span>
<span style="color: #008080;">37</span>             <span style="color: #0000ff;">if</span>(user==<span style="color: #0000ff;">null</span><span style="color: #000000;">)
</span><span style="color: #008080;">38</span>             <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">null</span><span style="color: #000000;">;
</span><span style="color: #008080;">39</span> 
<span style="color: #008080;">40</span>             <span style="color: #008000;">//</span><span style="color: #008000;">否则验证成功，生成jwt token</span>
<span style="color: #008080;">41</span>             <span style="color: #0000ff;">var</span> tokenHandler=<span style="color: #0000ff;">new</span><span style="color: #000000;"> JwtSecurityTokenHandler();
</span><span style="color: #008080;">42</span>             <span style="color: #0000ff;">var</span> key=<span style="color: #000000;">Encoding.ASCII.GetBytes(_appSettings.Secret);
</span><span style="color: #008080;">43</span>             <span style="color: #0000ff;">var</span> tokenDescriptor=<span style="color: #0000ff;">new</span><span style="color: #000000;"> SecurityTokenDescriptor
</span><span style="color: #008080;">44</span> <span style="color: #000000;">            {
</span><span style="color: #008080;">45</span>                 Subject=<span style="color: #0000ff;">new</span> ClaimsIdentity(<span style="color: #0000ff;">new</span><span style="color: #000000;"> Claim[]{
</span><span style="color: #008080;">46</span>                     <span style="color: #0000ff;">new</span><span style="color: #000000;"> Claim(ClaimTypes.Name,user.Id.ToString())
</span><span style="color: #008080;">47</span> <span style="color: #000000;">                }),
</span><span style="color: #008080;">48</span>                 Expires=DateTime.UtcNow.AddDays(<span style="color: #800080;">7</span><span style="color: #000000;">),
</span><span style="color: #008080;">49</span>                 SigningCredentials=<span style="color: #0000ff;">new</span> SigningCredentials(<span style="color: #0000ff;">new</span><span style="color: #000000;"> SymmetricSecurityKey(key),SecurityAlgorithms.HmacSha256Signature)
</span><span style="color: #008080;">50</span> <span style="color: #000000;">            };
</span><span style="color: #008080;">51</span>             <span style="color: #0000ff;">var</span> token=<span style="color: #000000;">tokenHandler.CreateToken(tokenDescriptor);
</span><span style="color: #008080;">52</span>             user.Token=<span style="color: #000000;">tokenHandler.WriteToken(token);
</span><span style="color: #008080;">53</span>             <span style="color: #0000ff;">return</span><span style="color: #000000;"> user.WithoutPassword();
</span><span style="color: #008080;">54</span> 
<span style="color: #008080;">55</span> <span style="color: #000000;">        }
</span><span style="color: #008080;">56</span> 
<span style="color: #008080;">57</span>         <span style="color: #0000ff;">public</span> IEnumerable&lt;User&gt;<span style="color: #000000;"> GetAll()
</span><span style="color: #008080;">58</span> <span style="color: #000000;">        {
</span><span style="color: #008080;">59</span>             <span style="color: #0000ff;">return</span><span style="color: #000000;"> _users.WithoutPasswords();
</span><span style="color: #008080;">60</span> <span style="color: #000000;">        }
</span><span style="color: #008080;">61</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">62</span> }</span></pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/copycode.gif" alt="复制代码"></a></span></div></div>
<p><span style="font-family: &#39;Microsoft YaHei&#39;;">&nbsp;</span></p>
<h4 align="left" id="autoid-4-0-7"><span style="color: #ff6600; font-family: &#39;Microsoft YaHei&#39;;">/appsettings.Development.json</span></h4>
<p><span style="font-family: &#39;Microsoft YaHei&#39;;">具有特定于开发环境的应用程序设置的配置文件</span></p>
<div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/copycode.gif" alt="复制代码"></a></span></div>
<pre><span style="font-family: &#39;Microsoft YaHei&#39;;"><span style="color: #000000;">{
  </span><span style="color: #800000;">"</span><span style="color: #800000;">Logging</span><span style="color: #800000;">"</span><span style="color: #000000;">: {
    </span><span style="color: #800000;">"</span><span style="color: #800000;">LogLevel</span><span style="color: #800000;">"</span><span style="color: #000000;">: {
      </span><span style="color: #800000;">"</span><span style="color: #800000;">Default</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">Debug</span><span style="color: #800000;">"</span><span style="color: #000000;">,
      </span><span style="color: #800000;">"</span><span style="color: #800000;">System</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">Information</span><span style="color: #800000;">"</span><span style="color: #000000;">,
      </span><span style="color: #800000;">"</span><span style="color: #800000;">Microsoft</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">Information</span><span style="color: #800000;">"</span><span style="color: #000000;">
    }
  }
}</span></span></pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/copycode.gif" alt="复制代码"></a></span></div></div>
<h4 align="left" id="autoid-4-0-8"><span style="color: #ff6600; font-family: &#39;Microsoft YaHei&#39;;">&nbsp;/appsettings.json</span></h4>
<p align="left"><span style="font-family: &#39;Microsoft YaHei&#39;;">包含所有环境的应用程序设置的根配置文件。</span></p>
<p align="left"><span style="font-family: &#39;Microsoft YaHei&#39;;"><span style="color: #ff6600;">重要说明</span>：Api使用Secret属性来签名和验证用于身份验证的JWT令牌，并使用您自己的随机字符串对其进行更新，以确保其他人无法生成JWT来获得对您的应用程序的未授权访问</span></p>
<div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/copycode.gif" alt="复制代码"></a></span></div>
<pre><span style="font-family: &#39;Microsoft YaHei&#39;;"><span style="color: #000000;">{
  </span><span style="color: #800000;">"</span><span style="color: #800000;">AppSettings</span><span style="color: #800000;">"</span><span style="color: #000000;">: {
    </span><span style="color: #800000;">"</span><span style="color: #800000;">Secret</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">THIS IS USED TO SIGN AND VERIFY JWT TOKENS, REPLACE IT WITH YOUR OWN SECRET, IT CAN BE ANY STRING</span><span style="color: #800000;">"</span><span style="color: #000000;">
  },
  </span><span style="color: #800000;">"</span><span style="color: #800000;">Logging</span><span style="color: #800000;">"</span><span style="color: #000000;">: {
    </span><span style="color: #800000;">"</span><span style="color: #800000;">LogLevel</span><span style="color: #800000;">"</span><span style="color: #000000;">: {
      </span><span style="color: #800000;">"</span><span style="color: #800000;">Default</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">Warning</span><span style="color: #800000;">"</span><span style="color: #000000;">
    }
  },
  </span><span style="color: #800000;">"</span><span style="color: #800000;">AllowedHosts</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">*</span><span style="color: #800000;">"</span><span style="color: #000000;">
}</span></span></pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/copycode.gif" alt="复制代码"></a></span></div></div>
<h4 align="left" id="autoid-4-0-9"><span style="color: #ff6600; font-family: &#39;Microsoft YaHei&#39;;">/Program.cs</span></h4>
<p align="left"><span style="font-family: &#39;Microsoft YaHei&#39;;">Program.cs是一个控制台应用程序，它是启动该应用程序的主要入口点。它使用IHostBuilder的实例配置和启动web api主机和web服务器。ASP.NET Core应用程序需要一个host去执行。</span></p>
<p align="left"><span style="font-family: &#39;Microsoft YaHei&#39;;">Kestrel是示例中使用的Web服务器，它是ASP.NET Core的一种新的狂平台的web服务器，默认包含在新项目模板中。Kestrel本身可以很好的用于内部应用程序的开发，但是在一些公共网站和应用程序中，建议使用反向代理服务器（IIS,Apache，Nginx），一个反向代理服务器接收来自网络的HTTP请求并且在经过一些初步处理后将请求转发到Kestrel。</span></p>
<div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/copycode.gif" alt="复制代码"></a></span></div>
<pre><span style="font-family: &#39;Microsoft YaHei&#39;;"><span style="color: #008080;"> 1</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> Microsoft.AspNetCore.Hosting;
</span><span style="color: #008080;"> 2</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> Microsoft.Extensions.Hosting;
</span><span style="color: #008080;"> 3</span> 
<span style="color: #008080;"> 4</span> <span style="color: #0000ff;">namespace</span><span style="color: #000000;"> JwtAuthDemo
</span><span style="color: #008080;"> 5</span> <span style="color: #000000;">{
</span><span style="color: #008080;"> 6</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> Program
</span><span style="color: #008080;"> 7</span> <span style="color: #000000;">    {
</span><span style="color: #008080;"> 8</span>         <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> Main(<span style="color: #0000ff;">string</span><span style="color: #000000;">[] args)
</span><span style="color: #008080;"> 9</span> <span style="color: #000000;">        {
</span><span style="color: #008080;">10</span> <span style="color: #000000;">            CreateHostBuilder(args).Build().Run();
</span><span style="color: #008080;">11</span> <span style="color: #000000;">        }
</span><span style="color: #008080;">12</span>          <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> IHostBuilder CreateHostBuilder(<span style="color: #0000ff;">string</span>[] args) =&gt;
<span style="color: #008080;">13</span> <span style="color: #000000;">            Host.CreateDefaultBuilder(args)
</span><span style="color: #008080;">14</span>                 .ConfigureWebHostDefaults(webBuilder =&gt;
<span style="color: #008080;">15</span> <span style="color: #000000;">                {
</span><span style="color: #008080;">16</span>                     webBuilder.UseStartup&lt;Startup&gt;<span style="color: #000000;">()
</span><span style="color: #008080;">17</span>                         .UseUrls(<span style="color: #800000;">"</span><span style="color: #800000;">http://localhost:1022</span><span style="color: #800000;">"</span><span style="color: #000000;">);
</span><span style="color: #008080;">18</span> <span style="color: #000000;">                });
</span><span style="color: #008080;">19</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">20</span> }</span></pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/copycode.gif" alt="复制代码"></a></span></div></div>
<p><span style="font-family: &#39;Microsoft YaHei&#39;;">&nbsp;</span></p>
<h4 align="left" id="autoid-4-0-10"><span style="color: #ff6600; font-family: &#39;Microsoft YaHei&#39;;">/Startup.cs</span></h4>
<p align="left"><span style="font-family: &#39;Microsoft YaHei&#39;;">Startup类用于配置应用程序的请求管道以及如何处理这些请求。</span></p>
<div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/copycode.gif" alt="复制代码"></a></span></div>
<pre><span style="font-family: &#39;Microsoft YaHei&#39;;"><span style="color: #008080;"> 1</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> Microsoft.AspNetCore.Builder;
</span><span style="color: #008080;"> 2</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> Microsoft.AspNetCore.Hosting;
</span><span style="color: #008080;"> 3</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> Microsoft.Extensions.Configuration;
</span><span style="color: #008080;"> 4</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> Microsoft.Extensions.DependencyInjection;
</span><span style="color: #008080;"> 5</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> JwtAuthDemo.IServices;
</span><span style="color: #008080;"> 6</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> JwtAuthDemo.Services;
</span><span style="color: #008080;"> 7</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> JwtAuthDemo.Helper;
</span><span style="color: #008080;"> 8</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> Microsoft.AspNetCore.Authentication.JwtBearer;
</span><span style="color: #008080;"> 9</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> Microsoft.IdentityModel.Tokens;
</span><span style="color: #008080;">10</span> <span style="color: #0000ff;">using</span><span style="color: #000000;"> System.Text;
</span><span style="color: #008080;">11</span> <span style="color: #0000ff;">namespace</span><span style="color: #000000;"> JwtAuthDemo
</span><span style="color: #008080;">12</span> <span style="color: #000000;">{
</span><span style="color: #008080;">13</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> Startup
</span><span style="color: #008080;">14</span> <span style="color: #000000;">    {
</span><span style="color: #008080;">15</span>         <span style="color: #0000ff;">public</span><span style="color: #000000;"> Startup(IConfiguration configuration)
</span><span style="color: #008080;">16</span> <span style="color: #000000;">        {
</span><span style="color: #008080;">17</span>             Configuration =<span style="color: #000000;"> configuration;
</span><span style="color: #008080;">18</span> <span style="color: #000000;">        }
</span><span style="color: #008080;">19</span> 
<span style="color: #008080;">20</span>         <span style="color: #0000ff;">public</span> IConfiguration Configuration { <span style="color: #0000ff;">get</span><span style="color: #000000;">; }
</span><span style="color: #008080;">21</span> 
<span style="color: #008080;">22</span>         <span style="color: #008000;">//</span><span style="color: #008000;"> This method gets called by the runtime. Use this method to add services to the container.</span>
<span style="color: #008080;">23</span>         <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> ConfigureServices(IServiceCollection services)
</span><span style="color: #008080;">24</span> <span style="color: #000000;">        {
</span><span style="color: #008080;">25</span> <span style="color: #000000;">            services.AddCors();
</span><span style="color: #008080;">26</span> <span style="color: #000000;">            services.AddControllers();
</span><span style="color: #008080;">27</span>              <span style="color: #0000ff;">var</span> appSettingsSection = Configuration.GetSection(<span style="color: #800000;">"</span><span style="color: #800000;">AppSettings</span><span style="color: #800000;">"</span><span style="color: #000000;">);
</span><span style="color: #008080;">28</span>             services.Configure&lt;AppSettings&gt;<span style="color: #000000;">(appSettingsSection);
</span><span style="color: #008080;">29</span>             <span style="color: #008000;">//</span><span style="color: #008000;"> configure jwt authentication</span>
<span style="color: #008080;">30</span>             <span style="color: #0000ff;">var</span> appSettings = appSettingsSection.Get&lt;AppSettings&gt;<span style="color: #000000;">();
</span><span style="color: #008080;">31</span>             <span style="color: #0000ff;">var</span> key =<span style="color: #000000;"> Encoding.ASCII.GetBytes(appSettings.Secret);
</span><span style="color: #008080;">32</span>             services.AddAuthentication(x =&gt;
<span style="color: #008080;">33</span> <span style="color: #000000;">            {
</span><span style="color: #008080;">34</span>                 x.DefaultAuthenticateScheme =<span style="color: #000000;"> JwtBearerDefaults.AuthenticationScheme;
</span><span style="color: #008080;">35</span>                 x.DefaultChallengeScheme =<span style="color: #000000;"> JwtBearerDefaults.AuthenticationScheme;
</span><span style="color: #008080;">36</span> <span style="color: #000000;">            })
</span><span style="color: #008080;">37</span>              .AddJwtBearer(x =&gt;
<span style="color: #008080;">38</span> <span style="color: #000000;">            {
</span><span style="color: #008080;">39</span>                 x.RequireHttpsMetadata = <span style="color: #0000ff;">false</span><span style="color: #000000;">;
</span><span style="color: #008080;">40</span>                 x.SaveToken = <span style="color: #0000ff;">true</span><span style="color: #000000;">;
</span><span style="color: #008080;">41</span>                 x.TokenValidationParameters = <span style="color: #0000ff;">new</span><span style="color: #000000;"> TokenValidationParameters
</span><span style="color: #008080;">42</span> <span style="color: #000000;">                {
</span><span style="color: #008080;">43</span>                     ValidateIssuerSigningKey = <span style="color: #0000ff;">true</span><span style="color: #000000;">,
</span><span style="color: #008080;">44</span>                     IssuerSigningKey = <span style="color: #0000ff;">new</span><span style="color: #000000;"> SymmetricSecurityKey(key),
</span><span style="color: #008080;">45</span>                     ValidateIssuer = <span style="color: #0000ff;">false</span><span style="color: #000000;">,
</span><span style="color: #008080;">46</span>                     ValidateAudience = <span style="color: #0000ff;">false</span>
<span style="color: #008080;">47</span> <span style="color: #000000;">                };
</span><span style="color: #008080;">48</span> <span style="color: #000000;">            });
</span><span style="color: #008080;">49</span>               <span style="color: #008000;">//</span><span style="color: #008000;"> configure DI for application services</span>
<span style="color: #008080;">50</span>             services.AddScoped&lt;IUserService, UserService&gt;<span style="color: #000000;">();
</span><span style="color: #008080;">51</span> <span style="color: #000000;">        }
</span><span style="color: #008080;">52</span> 
<span style="color: #008080;">53</span>         <span style="color: #008000;">//</span><span style="color: #008000;"> This method gets called by the runtime. Use this method to configure the HTTP request pipeline.</span>
<span style="color: #008080;">54</span>         <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> Configure(IApplicationBuilder app, IWebHostEnvironment env)
</span><span style="color: #008080;">55</span> <span style="color: #000000;">        {
</span><span style="color: #008080;">56</span> <span style="color: #000000;">             app.UseRouting();
</span><span style="color: #008080;">57</span> 
<span style="color: #008080;">58</span>             <span style="color: #008000;">//</span><span style="color: #008000;"> global cors policy</span>
<span style="color: #008080;">59</span>             app.UseCors(x =&gt;<span style="color: #000000;"> x
</span><span style="color: #008080;">60</span> <span style="color: #000000;">                .AllowAnyOrigin()
</span><span style="color: #008080;">61</span> <span style="color: #000000;">                .AllowAnyMethod()
</span><span style="color: #008080;">62</span> <span style="color: #000000;">                .AllowAnyHeader());
</span><span style="color: #008080;">63</span> 
<span style="color: #008080;">64</span> <span style="color: #000000;">            app.UseAuthentication();
</span><span style="color: #008080;">65</span> <span style="color: #000000;">            app.UseAuthorization();
</span><span style="color: #008080;">66</span>             
<span style="color: #008080;">67</span>             app.UseEndpoints(endpoints =&gt;<span style="color: #000000;"> {
</span><span style="color: #008080;">68</span> <span style="color: #000000;">                endpoints.MapControllers();
</span><span style="color: #008080;">69</span> <span style="color: #000000;">            });
</span><span style="color: #008080;">70</span> <span style="color: #000000;">        }
</span><span style="color: #008080;">71</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">72</span> }</span></pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/copycode.gif" alt="复制代码"></a></span></div></div>
<p><span style="font-family: &#39;Microsoft YaHei&#39;;">&nbsp;</span></p>
<h4 align="left" id="autoid-4-0-11"><span style="color: #ff6600; font-family: &#39;Microsoft YaHei&#39;;">&nbsp;/JwtAuthDemo.csproj</span></h4>
<p align="left"><span style="font-family: &#39;Microsoft YaHei&#39;;">csproj（C＃项目）是一个基于MSBuild的文件，其中包含目标框架和应用程序的NuGet包依赖项信息。</span></p>
<div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/copycode.gif" alt="复制代码"></a></span></div>
<pre><span style="font-family: &#39;Microsoft YaHei&#39;;">&lt;Project Sdk=<span style="color: #800000;">"</span><span style="color: #800000;">Microsoft.NET.Sdk.Web</span><span style="color: #800000;">"</span>&gt;

  &lt;PropertyGroup&gt;
    &lt;TargetFramework&gt;netcoreapp3.<span style="color: #800080;">1</span>&lt;/TargetFramework&gt;
    &lt;AspNetCoreHostingModel&gt;InProcess&lt;/AspNetCoreHostingModel&gt;
  &lt;/PropertyGroup&gt;

  &lt;ItemGroup&gt;
   &lt;PackageReference Include=<span style="color: #800000;">"</span><span style="color: #800000;">Microsoft.AspNetCore.Authentication.JwtBearer</span><span style="color: #800000;">"</span> Version=<span style="color: #800000;">"</span><span style="color: #800000;">3.1.0</span><span style="color: #800000;">"</span> /&gt;
    &lt;PackageReference Include=<span style="color: #800000;">"</span><span style="color: #800000;">System.IdentityModel.Tokens.Jwt</span><span style="color: #800000;">"</span> Version=<span style="color: #800000;">"</span><span style="color: #800000;">5.6.0</span><span style="color: #800000;">"</span> /&gt;
  &lt;/ItemGroup&gt;

&lt;/Project&gt;</span></pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/copycode.gif" alt="复制代码"></a></span></div></div>
<p><span style="font-family: &#39;Microsoft YaHei&#39;;">&nbsp;</span></p>
<p><span style="font-family: &#39;Microsoft YaHei&#39;;">下一篇，我们将会介绍如何用单页面应用程序Vue.js来调用此API.</span></p>
<p align="left"><span style="font-family: &#39;Microsoft YaHei&#39;;">&nbsp;</span></p>
<p><span style="font-family: &#39;Microsoft YaHei&#39;;">&nbsp;</span></p>
<p align="left"><span style="font-family: &#39;Microsoft YaHei&#39;;">&nbsp;</span></p>
</div>
<div id="MySignature"></div>
<div class="clear"></div>
<div id="blog_post_info_block">
<div id="EntryTag">
    标签: 
            <a href="https://www.cnblogs.com/yixuanhan/tag/ASP.NET%20CORE/">ASP.NET CORE</a>,             <a href="https://www.cnblogs.com/yixuanhan/tag/JWT/">JWT</a></div>

    <div id="blog_post_info">
<div id="green_channel">
        <a href="javascript:void(0);" id="green_channel_digg" onclick="DiggIt(12593724,cb_blogId,1);green_channel_success(this,&#39;谢谢推荐！&#39;);">好文要顶</a>
        <a id="green_channel_follow" onclick="follow(&#39;8304ac90-5228-e411-b908-9dcfd8948a71&#39;);" href="javascript:void(0);">关注我</a>
    <a id="green_channel_favorite" onclick="AddToWz(cb_entryId);return false;" href="javascript:void(0);">收藏该文</a>
    <a id="green_channel_weibo" href="javascript:void(0);" title="分享至新浪微博" onclick="ShareToTsina()"><img src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/icon_weibo_24.png" alt=""></a>
    <a id="green_channel_wechat" href="javascript:void(0);" title="分享至微信" onclick="shareOnWechat()"><img src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/wechat.png" alt=""></a>
</div>
<div id="author_profile">
    <div id="author_profile_info" class="author_profile_info">
            <a href="https://home.cnblogs.com/u/yixuanhan/" target="_blank"><img src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/20191029104543.png" class="author_avatar" alt=""></a>
        <div id="author_profile_detail" class="author_profile_info">
            <a href="https://home.cnblogs.com/u/yixuanhan/">yixuan.han</a><br>
            <a href="https://home.cnblogs.com/u/yixuanhan/followees/">关注 - 22</a><br>
            <a href="https://home.cnblogs.com/u/yixuanhan/followers/">粉丝 - 19</a>
        </div>
    </div>
    <div class="clear"></div>
    <div id="author_profile_honor"></div>
    <div id="author_profile_follow">
                <a href="javascript:void(0);" onclick="follow(&#39;8304ac90-5228-e411-b908-9dcfd8948a71&#39;);return false;">+加关注</a>
    </div>
</div>
<div id="div_digg">
    <div class="diggit" onclick="votePost(12593724,&#39;Digg&#39;)">
        <span class="diggnum" id="digg_count">0</span>
    </div>
    <div class="buryit" onclick="votePost(12593724,&#39;Bury&#39;)">
        <span class="burynum" id="bury_count">0</span>
    </div>
    <div class="clear"></div>
    <div class="diggword" id="digg_tips">
    </div>
</div>

<script type="text/javascript">
    currentDiggType = 0;
</script></div>
    <div class="clear"></div>
    <div id="post_next_prev">

    <a href="https://www.cnblogs.com/yixuanhan/p/11691303.html" class="p_n_p_prefix">« </a> 上一篇：    <a href="https://www.cnblogs.com/yixuanhan/p/11691303.html" title="发布于 2019-10-17 12:28">.NET Core 3.0中IAsyncEnumerable&lt;T&gt;有什么大不了的?</a>

</div>
</div>
            </div>
            <div class="postDesc">posted @ 
<span id="post-date">2020-03-29 19:25</span>&nbsp;
<a href="https://www.cnblogs.com/yixuanhan/">yixuan.han</a>&nbsp;
阅读(<span id="post_view_count">60</span>)&nbsp;
评论(<span id="post_comment_count">0</span>)&nbsp;
<a href="https://i.cnblogs.com/EditPosts.aspx?postid=12593724" rel="nofollow">编辑</a>&nbsp;
<a href="javascript:void(0)" onclick="AddToWz(12593724);return false;">收藏</a></div>
        </div>
	    
	    
    </div><!--end: topics 文章、评论容器-->
</div>
<script src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/highlight.min.js.下载"></script>
<script>markdown_highlight();</script>
<script>
    var allowComments = true, cb_blogId = 195723, cb_blogApp = 'yixuanhan', cb_blogUserGuid = '8304ac90-5228-e411-b908-9dcfd8948a71';
    var cb_entryId = 12593724, cb_entryCreatedDate = '2020-03-29 19:25', cb_postType = 1; 
    loadViewCount(cb_entryId);
    loadSideColumnAd();
</script><a name="!comments"></a>
<div id="blog-comments-placeholder"></div>
<script>
    var commentManager = new blogCommentManager();
    commentManager.renderComments(0);
</script>

<div id="comment_form" class="commentform">
    <a name="commentform"></a>
    <div id="divCommentShow"></div>
    <div id="comment_nav"><span id="span_refresh_tips"></span><a href="javascript:void(0);" onclick="return RefreshCommentList();" id="lnk_RefreshComments" runat="server" clientidmode="Static">刷新评论</a><a href="https://www.cnblogs.com/yixuanhan/p/12593724.html#" onclick="return RefreshPage();">刷新页面</a><a href="https://www.cnblogs.com/yixuanhan/p/12593724.html#top">返回顶部</a></div>
    <div id="comment_form_container" style="visibility: visible;"><div class="login_tips">
    注册用户登录后才能发表评论，请 
    <a rel="nofollow" href="javascript:void(0);" class="underline" onclick="return login(&#39;commentform&#39;);">登录</a>
     或 
    <a rel="nofollow" href="javascript:void(0);" class="underline" onclick="return register();">注册</a>，
    <a href="https://www.cnblogs.com/">访问</a> 网站首页。
</div></div>
    <div class="ad_text_commentbox" id="ad_text_under_commentbox"></div>
    <div id="ad_t2"><a href="http://www.ucancode.com/index.htm" target="_blank" onclick="ga(&#39;send&#39;, &#39;event&#39;, &#39;Link&#39;, &#39;click&#39;, &#39;T2-ucancode&#39;)">【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库</a><br><a href="https://cloud.tencent.com/act/seckill?fromSource=gwzcw.3498755.3498755.3498755&amp;utm_medium=cpc&amp;utm_id=gwzcw.3498755.3498755.3498755" target="_blank" onclick="ga(&#39;send&#39;, &#39;event&#39;, &#39;Link&#39;, &#39;click&#39;, &#39;T2-腾讯云&#39;)">【推荐】腾讯云产品限时秒杀，爆款1核2G云服务器99元/年！</a><br><a href="https://developer.aliyun.com/ask/257760?utm_content=g_1000088949" target="_blank" onclick="ga(&#39;send&#39;, &#39;event&#39;, &#39;Link&#39;, &#39;click&#39;, &#39;T2-阿里云开发者社区&#39;)">【推荐】精品问答：大数据计算技术 1000 问</a><br><a href="https://developer.aliyun.com/article/742341?utm_content=g_1000104145" target="_blank" onclick="ga(&#39;send&#39;, &#39;event&#39;, &#39;Link&#39;, &#39;click&#39;, &#39;T2-阿里云开发者社区&#39;)">【推荐】独家下载电子书 | 前端必看！阿里这样实现前端代码智能生成</a><br></div>
    <div id="opt_under_post"></div>
    <script async="async" src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/gpt.js.下载"></script>
    <script>
        var googletag = googletag || {};
        googletag.cmd = googletag.cmd || [];
    </script>
    <script>
        googletag.cmd.push(function () {
            googletag.defineSlot("/1090369/C1", [300, 250], "div-gpt-ad-1546353474406-0").addService(googletag.pubads());
            googletag.defineSlot("/1090369/C2", [468, 60], "div-gpt-ad-1539008685004-0").addService(googletag.pubads());
            googletag.pubads().enableSingleRequest();
            googletag.enableServices();
        });
    </script>
    <div id="cnblogs_c1" class="c_ad_block" style="">
        <div id="div-gpt-ad-1546353474406-0" style="height: 250px; width: 300px;"><div id="google_ads_iframe_/1090369/C1_0__container__" style="border: 0pt none; width: 300px; height: 250px;"></div></div>
    </div>
    <div id="under_post_news"></div>
    <div id="cnblogs_c2" class="c_ad_block" style="">
        <div id="div-gpt-ad-1539008685004-0" style="height: 60px; width: 468px;">
            <script>
                if (new Date() >= new Date(2018, 9, 13)) {
                    googletag.cmd.push(function () { googletag.display("div-gpt-ad-1539008685004-0"); });
                }
            </script>
        <div id="google_ads_iframe_/1090369/C2_0__container__" style="border: 0pt none; width: 468px; height: 60px;"></div></div>
    </div>
    <div id="under_post_kb">
<div class="itnews c_ad_block">
    <b>最新 IT 新闻</b>:
    <br>
 ·              <a href="https://news.cnblogs.com/n/660975/" target="_blank">谷歌对Android底层调整：支持蓝牙耳机快速与安卓设备配对</a>
            <br>
 ·              <a href="https://news.cnblogs.com/n/660974/" target="_blank">黑客良心发现？全球最大勒索病毒Troldesh终结：公开75万个密钥</a>
            <br>
 ·              <a href="https://news.cnblogs.com/n/660973/" target="_blank">天文奇观 NASA公布罕见双黑洞共舞现象：画面奇幻</a>
            <br>
 ·              <a href="https://news.cnblogs.com/n/660972/" target="_blank">卖家神器 阿里推出全球首个商品智能发布系统：工作量减少70%</a>
            <br>
 ·              <a href="https://news.cnblogs.com/n/660970/" target="_blank">李国庆向当当合作伙伴发函致歉： 夫妻纠纷不影响正常经营</a>
            <br>
    » <a href="https://news.cnblogs.com/" title="IT 新闻" target="_blank">更多新闻...</a>
</div></div>
    <div id="HistoryToday" class="c_ad_block"></div>
    <script type="text/javascript">
        fixPostBody();
        deliverBigBanner();
setTimeout(function() { incrementViewCount(cb_entryId); }, 50);        deliverAdT2();
        deliverAdC1();
        deliverAdC2();
        loadNewsAndKb();
        loadBlogSignature();
LoadPostCategoriesTags(cb_blogId, cb_entryId);        LoadPostInfoBlock(cb_blogId, cb_entryId, cb_blogApp, cb_blogUserGuid);
        GetPrevNextPost(cb_entryId, cb_blogId, cb_entryCreatedDate, cb_postType);
        loadOptUnderPost();
        GetHistoryToday(cb_blogId, cb_blogApp, cb_entryCreatedDate);
    </script>
</div>
	</div><!--end: forFlow -->
	</div><!--end: mainContent 主体内容容器-->

	<div id="sideBar">
		<div id="sideBarMain">
			
<div id="sidebar_news" class="newsItem"><!--done-->
<h3 class="catListTitle">公告</h3>

<div id="blog-news">
    <script type="text/javascript">window['__document_write_ajax_callbacks__']['5']();</script><script>window['__document_write_ajax_callbacks__']['1']();</script>
<script type="text/javascript">window['__document_write_ajax_callbacks__']['6']();</script><script type="text/javascript">window['__document_write_ajax_callbacks__']['7']();</script><script>window['__document_write_ajax_callbacks__']['2']();</script>


<script type="text/javascript">window['__document_write_ajax_callbacks__']['8']();</script><script type="text/javascript">window['__document_write_ajax_callbacks__']['3']();</script>
    <div id="profile_block">
        昵称：
        <a href="https://home.cnblogs.com/u/yixuanhan/">
            yixuan.han
        </a>
        <br>
        园龄：
        <a href="https://home.cnblogs.com/u/yixuanhan/" title="入园时间：2014-08-20">
            5年8个月
        </a>
        <br>
        粉丝：
        <a href="https://home.cnblogs.com/u/yixuanhan/followers/">
            19
        </a>
        <br>
        关注：
        <a href="https://home.cnblogs.com/u/yixuanhan/followees/">
            22
        </a>
        <div id="p_b_follow">
<a href="javascript:void(0)" onclick="follow(&#39;8304ac90-5228-e411-b908-9dcfd8948a71&#39;)">+加关注</a></div>
        <script type="text/javascript">window['__document_write_ajax_callbacks__']['9']();</script><script>window['__document_write_ajax_callbacks__']['4']();</script>
    </div>
</div>

</div>

<div id="sidebar_ad"></div>
			<div id="blog-calendar" style="">

<table id="blogCalendar" class="Cal" cellspacing="0" cellpadding="0" title="Calendar" border="0">
    <tbody>
        <tr>
            <td colspan="7">
                <table class="CalTitle" cellspacing="0" border="0">
                    <tbody>
                        <tr>
                            <td class="CalNextPrev">
                                <a href="javascript:void(0);" onclick="loadBlogCalendar(&#39;2020/03/30&#39;); return false;">&lt;</a>
                            </td>
                            <td align="center">2020年4月</td>
                            <td align="right" class="CalNextPrev">
                                <a href="javascript:void(0);" onclick="loadBlogCalendar(&#39;2020/05/30&#39;); return false;">&gt;</a>
                            </td>
                        </tr>
                    </tbody>
                </table>
            </td>
        </tr>
        <tr>
                    <th class="CalDayHeader" align="center" abbr="日" scope="col">日</th>
                    <th class="CalDayHeader" align="center" abbr="一" scope="col">一</th>
                    <th class="CalDayHeader" align="center" abbr="二" scope="col">二</th>
                    <th class="CalDayHeader" align="center" abbr="三" scope="col">三</th>
                    <th class="CalDayHeader" align="center" abbr="四" scope="col">四</th>
                    <th class="CalDayHeader" align="center" abbr="五" scope="col">五</th>
                    <th class="CalDayHeader" align="center" abbr="六" scope="col">六</th>
        </tr>
            <tr>
                            <td class="CalOtherMonthDay" align="center">29</td>
                            <td class="CalOtherMonthDay" align="center">30</td>
                            <td class="CalOtherMonthDay" align="center">31</td>
                        <td class="" align="center">
                            1
                        </td>
                        <td class="" align="center">
                            2
                        </td>
                        <td class="" align="center">
                            3
                        </td>
                    <td class="CalWeekendDay" align="center">
                        4
                    </td>
            </tr>
                <tr>
                        <td class="CalWeekendDay" align="center">
                            5
                        </td>
                            <td class="" align="center">
                                6
                            </td>
                            <td class="" align="center">
                                7
                            </td>
                            <td class="" align="center">
                                8
                            </td>
                            <td class="" align="center">
                                9
                            </td>
                            <td class="" align="center">
                                10
                            </td>
                        <td class="CalWeekendDay" align="center">
                            11
                        </td>
                </tr>
                <tr>
                        <td class="CalWeekendDay" align="center">
                            12
                        </td>
                            <td class="" align="center">
                                13
                            </td>
                            <td class="" align="center">
                                14
                            </td>
                            <td class="" align="center">
                                15
                            </td>
                            <td class="" align="center">
                                16
                            </td>
                            <td class="" align="center">
                                17
                            </td>
                        <td class="CalWeekendDay" align="center">
                            18
                        </td>
                </tr>
                <tr>
                        <td class="CalWeekendDay" align="center">
                            19
                        </td>
                            <td class="" align="center">
                                20
                            </td>
                            <td class="" align="center">
                                21
                            </td>
                            <td class="" align="center">
                                22
                            </td>
                            <td class="" align="center">
                                23
                            </td>
                            <td class="" align="center">
                                24
                            </td>
                        <td class="CalWeekendDay" align="center">
                            25
                        </td>
                </tr>
                <tr>
                        <td class="CalWeekendDay" align="center">
                            26
                        </td>
                            <td class="" align="center">
                                27
                            </td>
                            <td class="" align="center">
                                28
                            </td>
                            <td class="" align="center">
                                29
                            </td>
                            <td class="CalTodayDay" align="center">
                                30
                            </td>
                            <td class="CalOtherMonthDay" align="center">
                                1
                            </td>
                        <td class="CalOtherMonthDay" align="center">
                            2
                        </td>
                </tr>
                <tr>
                        <td class="CalOtherMonthDay" align="center">
                            3
                        </td>
                            <td class="CalOtherMonthDay" align="center">
                                4
                            </td>
                            <td class="CalOtherMonthDay" align="center">
                                5
                            </td>
                            <td class="CalOtherMonthDay" align="center">
                                6
                            </td>
                            <td class="CalOtherMonthDay" align="center">
                                7
                            </td>
                            <td class="CalOtherMonthDay" align="center">
                                8
                            </td>
                        <td class="CalOtherMonthDay" align="center">
                            9
                        </td>
                </tr>
    </tbody>
</table></div><script>loadBlogDefaultCalendar();</script>
			
			<div id="leftcontentcontainer">
				<div id="blog-sidecolumn">
<!-- 搜索 -->
<div id="sidebar_search" class="sidebar-block">
    <div id="sidebar_search" class="mySearch">
        <h3 class="catListTitle">搜索</h3>
        <div id="sidebar_search_box">
            <div id="widget_my_zzk" class="div_my_zzk">
                <input type="text" id="q" onkeydown="return zzk_go_enter(event);" class="input_my_zzk">&nbsp;<input onclick="zzk_go()" type="button" value="找找看" id="btnZzk" class="btn_my_zzk">
            </div>
            <div id="widget_my_google" class="div_my_zzk">
                <input type="text" name="google_q" id="google_q" onkeydown="return google_go_enter(event);" class="input_my_zzk">&nbsp;<input onclick="google_go()" type="button" value="谷歌搜索" class="btn_my_zzk">
            </div>
        </div>
    </div>
</div>

<!-- 常用链接 -->
<div id="sidebar_shortcut" class="sidebar-block">
    <div class="catListLink">
<h3 class="catListTitle">
常用链接
</h3>
<ul>
		<li>

<a href="https://www.cnblogs.com/yixuanhan/p/" title="我的博客的随笔列表">我的随笔</a>
</li>
		<li>

<a href="https://www.cnblogs.com/yixuanhan/MyComments.html" title="我的发表过的评论列表">我的评论</a>
</li>
		<li>

<a href="https://www.cnblogs.com/yixuanhan/OtherPosts.html" title="我评论过的随笔列表">我的参与</a>
</li>
		<li>

<a href="https://www.cnblogs.com/yixuanhan/RecentComments.html" title="我的博客的评论列表">最新评论</a>
</li>
		<li>

<a href="https://www.cnblogs.com/yixuanhan/tag/" title="我的博客的标签列表">我的标签</a>
</li>

</ul>
<div id="itemListLin_con" style="display:none;">
<ul>

</ul>
</div>
</div>


</div>

<!-- 最新随笔 -->



<!-- 我的标签 -->
<div id="sidebar_toptags" class="sidebar-block">
    <div class="catListTag">
<h3 class="catListTitle">我的标签</h3>
<ul>

        <li>
            <a href="https://www.cnblogs.com/yixuanhan/tag/ABP%20.NET%20C%23/">ABP .NET C#</a>(2)
        </li>
        <li>
            <a href="https://www.cnblogs.com/yixuanhan/tag/ASP.NET%20CORE/">ASP.NET CORE</a>(2)
        </li>
        <li>
            <a href="https://www.cnblogs.com/yixuanhan/tag/DDD/">DDD</a>(1)
        </li>
        <li>
            <a href="https://www.cnblogs.com/yixuanhan/tag/EF%20CORE/">EF CORE</a>(1)
        </li>
        <li>
            <a href="https://www.cnblogs.com/yixuanhan/tag/infopath/">infopath</a>(1)
        </li>
        <li>
            <a href="https://www.cnblogs.com/yixuanhan/tag/JWT/">JWT</a>(1)
        </li>
        <li>
            <a href="https://www.cnblogs.com/yixuanhan/tag/SQL%20SERVER%E6%8C%89%E5%A4%9A%E5%AD%97%E6%AE%B5%E6%9F%A5%E6%89%BE%E9%87%8D%E5%A4%8D%E7%9A%84%E6%95%B0%E6%8D%AE%E5%B9%B6%E5%88%A0%E9%99%A4%E5%8F%AA%E4%BF%9D%E7%95%99%E4%B8%80%E6%9D%A1/">SQL SERVER按多字段查找重复的数据并删除只保留一条</a>(1)
        </li>
        <li>
            <a href="https://www.cnblogs.com/yixuanhan/tag/.net%20core/">.net core</a>(1)
        </li>
        <li>
            <a href="https://www.cnblogs.com/yixuanhan/tag/ABP/">ABP</a>(1)
        </li>
    

</ul>
</div>


</div>

<!-- 积分与排名 -->


<!-- 随笔分类、随笔档案、文章分类、新闻分类、相册、链接 -->
<div id="sidebar_categories">
    
        <div id="sidebar_postcategory" class="catListPostCategory sidebar-block">
            <h3 class="catListTitle">
                

随笔分类



            </h3>


            <ul>

                        <li>
                            
<a href="https://www.cnblogs.com/yixuanhan/category/1237912.html" rel="" target="">
    .NET Core(9)
</a>
 

                        </li>
                        <li>
                            
<a href="https://www.cnblogs.com/yixuanhan/category/1279669.html" rel="" target="">
    ABP(ASP.NET Boilerplate)(14)
</a>
 

                        </li>
                        <li>
                            
<a href="https://www.cnblogs.com/yixuanhan/category/1251829.html" rel="" target="">
    Python(1)
</a>
 

                        </li>
                        <li>
                            
<a href="https://www.cnblogs.com/yixuanhan/category/1251834.html" rel="" target="">
    设计模式(1)
</a>
 

                        </li>
                        <li>
                            
<a href="https://www.cnblogs.com/yixuanhan/category/1009823.html" rel="" target="">
    微信小程序(3)
</a>
 

                        </li>
                        <li>
                            
<a href="https://www.cnblogs.com/yixuanhan/category/1237911.html" rel="" target="">
    问题积累(6)
</a>
 

                        </li>

            </ul>


        </div>
        <div id="sidebar_postarchive" class="catListPostArchive sidebar-block">
            <h3 class="catListTitle">
                

随笔档案



            </h3>


            <ul>

                        <li>
                            
<a href="https://www.cnblogs.com/yixuanhan/archive/2020/03.html" rel="" target="">
    2020年3月(1)
</a>
 

                        </li>
                        <li>
                            
<a href="https://www.cnblogs.com/yixuanhan/archive/2019/10.html" rel="" target="">
    2019年10月(1)
</a>
 

                        </li>
                        <li>
                            
<a href="https://www.cnblogs.com/yixuanhan/archive/2019/07.html" rel="" target="">
    2019年7月(1)
</a>
 

                        </li>
                        <li>
                            
<a href="https://www.cnblogs.com/yixuanhan/archive/2019/05.html" rel="" target="">
    2019年5月(1)
</a>
 

                        </li>
                        <li>
                            
<a href="https://www.cnblogs.com/yixuanhan/archive/2019/04.html" rel="" target="">
    2019年4月(3)
</a>
 

                        </li>
                        <li>
                            
<a href="https://www.cnblogs.com/yixuanhan/archive/2018/11.html" rel="" target="">
    2018年11月(2)
</a>
 

                        </li>
                        <li>
                            
<a href="https://www.cnblogs.com/yixuanhan/archive/2018/09.html" rel="" target="">
    2018年9月(2)
</a>
 

                        </li>
                        <li>
                            
<a href="https://www.cnblogs.com/yixuanhan/archive/2018/08.html" rel="" target="">
    2018年8月(8)
</a>
 

                        </li>
                        <li>
                            
<a href="https://www.cnblogs.com/yixuanhan/archive/2018/07.html" rel="" target="">
    2018年7月(7)
</a>
 

                        </li>
                        <li>
                            
<a href="https://www.cnblogs.com/yixuanhan/archive/2018/06.html" rel="" target="">
    2018年6月(7)
</a>
 

                        </li>
                        <li>
                            
<a href="https://www.cnblogs.com/yixuanhan/archive/2018/03.html" rel="" target="">
    2018年3月(1)
</a>
 

                        </li>
                        <li>
                            
<a href="https://www.cnblogs.com/yixuanhan/archive/2017/07.html" rel="" target="">
    2017年7月(1)
</a>
 

                        </li>
                        <li>
                            
<a href="https://www.cnblogs.com/yixuanhan/archive/2017/06.html" rel="" target="">
    2017年6月(2)
</a>
 

                        </li>
                        <li>
                            
<a href="https://www.cnblogs.com/yixuanhan/archive/2017/05.html" rel="" target="">
    2017年5月(4)
</a>
 

                        </li>
                        <li>
                            
<a href="https://www.cnblogs.com/yixuanhan/archive/2017/04.html" rel="" target="">
    2017年4月(1)
</a>
 

                        </li>
                        <li>
                            
<a href="https://www.cnblogs.com/yixuanhan/archive/2017/02.html" rel="" target="">
    2017年2月(1)
</a>
 

                        </li>

            </ul>


        </div>

</div>

<!-- 最新评论 -->
<div id="sidebar_recentcomments" class="sidebar-block">
    <div class="catListComment">
<h3 class="catListTitle">最新评论</h3>

	<div class="RecentCommentBlock">
        <ul>
                    <li class="recent_comment_title"><a href="https://www.cnblogs.com/yixuanhan/p/9969466.html">1. Re:ABP之调试</a></li>
                    <li class="recent_comment_body">不能用啊！</li>
                    <li class="recent_comment_author">--lucky528</li>
                    <li class="recent_comment_title"><a href="https://www.cnblogs.com/yixuanhan/p/9396488.html">2. Re:如何使用ASP.NET Core、EF Core、ABP(ASP.NET Boilerplate)创建分层的Web应用程序（第一部分）</a></li>
                    <li class="recent_comment_body">不错，感谢分享，帮助很大</li>
                    <li class="recent_comment_author">--又见阿郎</li>
                    <li class="recent_comment_title"><a href="https://www.cnblogs.com/yixuanhan/p/11691303.html">3. Re:.NET Core 3.0中IAsyncEnumerable&lt;T&gt;有什么大不了的?</a></li>
                    <li class="recent_comment_body">mark</li>
                    <li class="recent_comment_author">--成天</li>
                    <li class="recent_comment_title"><a href="https://www.cnblogs.com/yixuanhan/p/11691303.html">4. Re:.NET Core 3.0中IAsyncEnumerable&lt;T&gt;有什么大不了的?</a></li>
                    <li class="recent_comment_body">但是这个要怎么返回给客户端啊？要配合signalR一起用嘛?</li>
                    <li class="recent_comment_author">--Yu2</li>
                    <li class="recent_comment_title"><a href="https://www.cnblogs.com/yixuanhan/p/11691303.html">5. Re:.NET Core 3.0中IAsyncEnumerable&lt;T&gt;有什么大不了的?</a></li>
                    <li class="recent_comment_body">不错的文章</li>
                    <li class="recent_comment_author">--wdwwtzy</li>
        </ul>
    </div>
</div>


</div>



<!-- 阅读排行榜 -->
<div id="sidebar_topviewedposts" class="sidebar-block">
    <div class="catListView">
<h3 class="catListTitle">阅读排行榜</h3>
	<div id="TopViewPostsBlock">
        <ul style="word-break:break-all">
                    <li>
                        <a href="https://www.cnblogs.com/yixuanhan/p/6796538.html">
                            1. 解决CPC撰写文档报错问题“无法获取“AxforApplication”控件的窗口句柄。不支持无窗口的 ActiveX 控件”(14662)
                        </a>
                    </li>
                    <li>
                        <a href="https://www.cnblogs.com/yixuanhan/p/9238781.html">
                            2. Dapper-小型ORM之王（C#.NET）(13837)
                        </a>
                    </li>
                    <li>
                        <a href="https://www.cnblogs.com/yixuanhan/p/9566342.html">
                            3. C#中的out 参数，ref参数，值参数(3251)
                        </a>
                    </li>
                    <li>
                        <a href="https://www.cnblogs.com/yixuanhan/p/9234004.html">
                            4. 如何在C#中使用Dapper（译）(3127)
                        </a>
                    </li>
                    <li>
                        <a href="https://www.cnblogs.com/yixuanhan/p/9596454.html">
                            5. C#类继承中构造函数的执行序列(3017)
                        </a>
                    </li>
        </ul>
    </div>
</div>


</div>

<!-- 评论排行榜 -->
<div id="sidebar_topcommentedposts" class="sidebar-block">
    <div class="catListFeedback">
<h3 class="catListTitle">评论排行榜</h3>
	<div id="TopFeedbackPostsBlock">
        <ul style="word-break:break-all">
                    <li>
                        <a href="https://www.cnblogs.com/yixuanhan/p/9566342.html">
                            1. C#中的out 参数，ref参数，值参数(6)
                        </a>
                    </li>
                    <li>
                        <a href="https://www.cnblogs.com/yixuanhan/p/9396488.html">
                            2. 如何使用ASP.NET Core、EF Core、ABP(ASP.NET Boilerplate)创建分层的Web应用程序（第一部分）(5)
                        </a>
                    </li>
                    <li>
                        <a href="https://www.cnblogs.com/yixuanhan/p/11691303.html">
                            3. .NET Core 3.0中IAsyncEnumerable&lt;T&gt;有什么大不了的?(3)
                        </a>
                    </li>
                    <li>
                        <a href="https://www.cnblogs.com/yixuanhan/p/9238781.html">
                            4. Dapper-小型ORM之王（C#.NET）(2)
                        </a>
                    </li>
                    <li>
                        <a href="https://www.cnblogs.com/yixuanhan/p/9283389.html">
                            5. Entity Framework Core系列之实战（ASP.NET Core  MVC应用程序）(2)
                        </a>
                    </li>
        </ul>
    </div>
</div>


</div>

<!-- 推荐排行榜 -->
<div id="sidebar_topdiggedposts" class="sidebar-block">
    
<div id="topdigg_posts_wrap">
    <div class="catListView">
        <h3 class="catListTitle">推荐排行榜</h3>
        <div id="TopDiggPostsBlock">
            <ul style="word-break: break-all">
                        <li>
                            <a href="https://www.cnblogs.com/yixuanhan/p/11691303.html">
                                1. .NET Core 3.0中IAsyncEnumerable&lt;T&gt;有什么大不了的?(7)
                            </a>
                        </li>
                        <li>
                            <a href="https://www.cnblogs.com/yixuanhan/p/9396488.html">
                                2. 如何使用ASP.NET Core、EF Core、ABP(ASP.NET Boilerplate)创建分层的Web应用程序（第一部分）(3)
                            </a>
                        </li>
                        <li>
                            <a href="https://www.cnblogs.com/yixuanhan/p/10647610.html">
                                3. ABP之session(2)
                            </a>
                        </li>
                        <li>
                            <a href="https://www.cnblogs.com/yixuanhan/p/9238781.html">
                                4. Dapper-小型ORM之王（C#.NET）(2)
                            </a>
                        </li>
                        <li>
                            <a href="https://www.cnblogs.com/yixuanhan/p/9263873.html">
                                5. Entity Framework Core系列之什么是Entity Framework Core(1)
                            </a>
                        </li>
            </ul>
        </div>
    </div>
</div>
</div></div>
                    <script>loadBlogSideColumn();</script>
			</div>
			
		</div><!--end: sideBarMain -->
	</div><!--end: sideBar 侧边栏容器 -->
	<div class="clear"></div>
	</div><!--end: main -->
	<div class="clear"></div>
	<div id="footer">
		<!--done-->
Copyright © 2020 yixuan.han
<br><span id="poweredby">Powered by .NET Core on Kubernetes</span>



	</div><!--end: footer -->
</div><!--end: home 自定义的最大容器 -->


    <div id="page_end_html">
        <script language="javascript" type="text/javascript">
// 生成目录索引列表
// ref: http://www.cnblogs.com/wangqiguo/p/4355032.html
// modified by: zzq
function GenerateContentList()
{
    var mainContent = $('#cnblogs_post_body');
    var h2_list = $('#cnblogs_post_body h2');//如果你的章节标题不是h2,只需要将这里的h2换掉即可

    if(mainContent.length < 1)
        return;
 
    if(h2_list.length>0)
    {
        var content = '<a name="_labelTop"></a>';
        content += '<div id="navCategory" style="color:#152e97;">';
        content += '<p style="font-size:18px;"><b>目录</b></p>';
        content += '<ul>';
        for(var i=0; i<h2_list.length; i++)
        {     
            var h3_list = $(h2_list[i]).nextAll("h3");
            var li3_content = '';
            for(var j=0; j<h3_list.length; j++)
            {
                var tmp = $(h3_list[j]).prevAll('h2').first();
                if(!tmp.is(h2_list[i]))
                    break;
                var li3_anchor = '<a name="_label' + i + '_' + j + '"></a>';
                $(h3_list[j]).before(li3_anchor);
                li3_content += '<li><a href="#_label' + i + '_' + j + '">' + $(h3_list[j]).text() + '</a></li>';
            }
            
            var li2_content = '';
            if(li3_content.length > 0)
                li2_content = '<li><a href="#_label' + i + '">' + $(h2_list[i]).text() + '</a><ul>' + li3_content + '</ul></li>';
            else
                li2_content = '<li><a href="#_label' + i + '">' + $(h2_list[i]).text() + '</a></li>';
            content += li2_content;
        }
        content += '</ul>';
        content += '</div><p>&nbsp;</p>';
        content += '<hr style="height:1px;border:none;border-top:1px dashed #0066CC;"/>';
        if($('#cnblogs_post_body').length != 0 )
        {
            $($('#cnblogs_post_body')[0]).prepend(content);
        }
    }   
}

GenerateContentList();
</script>
    </div>

<script type="text/javascript">
window.tctipConfig = {
        imagePrefix: "https://files.cnblogs.com/files/kdy11/",
        cssPrefix:     "https://files.cnblogs.com/files/kdy11",
        buttonImageId:  4,
        buttonTip:  "dashang",
        list:{
            alipay: {qrimg: "https://files.cnblogs.com/files/yixuanhan/zfb.bmp"},
            weixin:{qrimg: "https://files.cnblogs.com/files/yixuanhan/wx.bmp"},
        }
};
</script><link type="text/css" rel="stylesheet" href="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/myRewards.css"><div id="myRewards" class="myRewards" style="width: 0px;"><a class="btn-myRewards" href="javascript:;"><img class="png" src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/tab_4.bmp"></a><div class="myRewards-main"><h1 class="myR-h">喜欢请打赏</h1><div class="myRewardsbox"><div class="myRewards-list"><ul class="not-full"><li class=""><a href="javascript:;">支付宝<img class="png" src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/alipay.bmp" alt="支付宝"></a></li><li class="myR-on"><a href="javascript:;">微信<img class="png" src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/weixin.bmp" alt="微信"></a></li></ul></div><div class="myRewards-detail"><div class="myRewards-ubox"><p class="myRewards-code-tit">扫描二维码打赏</p><div class="myRewards-code"><img src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/wx.bmp"></div><p class="myRewards-account">微信打赏</p></div></div></div><p class="myR-bot"><a href="https://github.com/greedying/tctip" target="_blank">了解更多</a></p></div></div><script src="./JWT在ASP.NET Core3.1的应用 - yixuan.han - 博客园_files/index"></script><script type="text/javascript">
      //以下是锚点JS
      var a = $(document);
      a.ready(function() {
        var b = $('body'),
          d = 'sideToolbar',
          e = 'sideCatalog',
          f = 'sideCatalog-catalog',
          g = 'sideCatalogBtn',
          h = 'sideToolbar-up',
          i = '<div id="sideToolbar"style="display:none;">\<div class="sideCatalogBg"id="sideCatalog">\<div id="sideCatalog-sidebar">\<div class="sideCatalog-sidebar-top"></div>\<div class="sideCatalog-sidebar-bottom"></div>\</div>\<div id="sideCatalog-catalog">\<ul class="nav"style="width:225px;zoom:1">\</ul>\</div>\</div>\<a href="javascript:void(0);"id="sideCatalogBtn"class="sideCatalogBtnDisable"></a>\</div>',
          j = '',
          k = 200,
          l = 0,
          m = 0,
          n = 0,
          //限制存在个数，如数量过多，则只显示h2，不显示h3
          //o, p = 13,
          o, p = 100,
          q = true,
          r = true,
          s = b;
        if(s.length === 0) {
          return
        };
        b.append(i);
        //指定获取目录的范围-------------这一点非常重要，因为每个人指定的范围都不一样，所以这是要修改的地方
        //o = s.find(':header');
        o = $('#cnblogs_post_body').find(':header')
        if(o.length > p) {
          r = false;
          var t = s.find('h2');
          var u = s.find('h3');
          if(t.length + u.length > p) {
            q = false
          }
        };
        o.each(function(t) {
          var u = $(this),
            v = u[0];

          var title = u.text();
          var text = u.text();

          u.attr('id', 'autoid-' + l + '-' + m + '-' + n)
          //if (!u.attr('id')) {
          //    u.attr('id', 'autoid-' + l + '-' + m + '-' + n)
          //};
          if(v.localName === 'h2') {
            l++;
            m = 0;
            if(text.length > 14) text = text.substr(0, 20) + "...";
            j += '<li><span>' + l + '&nbsp&nbsp</span><a href="#' + u.attr('id') + '" title="' + title + '">' + text + '</a><span class="sideCatalog-dot"></span></li>';
          } else if(v.localName === 'h3') {
            m++;
            n = 0;
            if(q) {
              if(text.length > 12) text = text.substr(0, 16) + "...";
              j += '<li class="h2Offset"><span>' + l + '.' + m + '&nbsp&nbsp</span><a href="#' + u.attr('id') + '" title="' + title + '">' + text + '</a></li>';
            }
          } else if(v.localName === 'h4') {
            n++;
            if(r) {
              j += '<li class="h3Offset"><span>' + l + '.' + m + '.' + n + '&nbsp&nbsp</span><a href="#' + u.attr('id') + '" title="' + title + '">' + u.text() + '</a></li>';
            }
          }
        });
        $('#' + f + '>ul').html(j);
        b.data('spy', 'scroll');
        b.data('target', '.sideCatalogBg');
        $('body').scrollspy({
          target: '.sideCatalogBg'
        });
        $sideCatelog = $('#' + e);
        $('#' + g).on('click', function() {
          if($(this).hasClass('sideCatalogBtnDisable')) {
            $sideCatelog.css('visibility', 'hidden')
          } else {
            $sideCatelog.css('visibility', 'visible')
          };
          $(this).toggleClass('sideCatalogBtnDisable')
        });
        $('#' + h).on('click', function() {
          $("html,body").animate({
            scrollTop: 0
          }, 500)
        });
        $sideToolbar = $('#' + d);

        //通过判断评论框是否存在显示索引目录
        var commentDiv = $("#blog-comments-placeholder");

        a.on('scroll', function() {
          //评论框存在才调用方法
          if(commentDiv.length > 0) {
            var t = a.scrollTop();
            if(t > k) {
              $sideToolbar.css('display', 'block');
              $('#gotop').show()
            } else {
              $sideToolbar.css('display', 'none')
              $('#gotop').hide()
            }
          }
        })
      });
      //以上是锚点JS
      //以下是返回顶部JS
      $(function() {
        $('body').append('<div id="gotop" onclick="goTop();"></div>');
      });

      function goTop(u, t, r) {
        var scrollActivate = !0;
        if(scrollActivate) {
          u = u || 0.1;
          t = t || 16;
          var s = 0,
            q = 0,
            o = 0,
            p = 0,
            n = 0,
            j = 0;
          document.documentElement && (s = document.documentElement.scrollLeft || 0, q = document.documentElement.scrollTop || 0);
          document.body && (o = document.body.scrollLeft || 0, p = document.body.scrollTop || 0);
          n = window.scrollX || 0;
          j = window.scrollY || 0;
          s = Math.max(s, Math.max(o, n));
          q = Math.max(q, Math.max(p, j));
          p = 1 + u;
          window.scrollTo(Math.floor(s / p), Math.floor(q / p));
          0 < s || 0 < q ? window.setTimeout('goTop(' + u + ', ' + t + ')', t) : 'undefined' != typeof r && r()
        } else {
          scrollActivate = !0
        }
      }
      //以上是返回顶部JS
    </script><div id="sideToolbar" style="display:none;"><div class="sideCatalogBg" id="sideCatalog"><div id="sideCatalog-sidebar"><div class="sideCatalog-sidebar-top"></div><div class="sideCatalog-sidebar-bottom"></div></div><div id="sideCatalog-catalog"><ul class="nav" style="width:225px;zoom:1"><li><span>1&nbsp;&nbsp;</span><a href="https://www.cnblogs.com/yixuanhan/p/12593724.html#autoid-0-0-0" title="开发ASP.NET CORE 3.1应用程序所需的工具">开发ASP.NET CORE 3.1应用...</a><span class="sideCatalog-dot"></span></li><li><span>2&nbsp;&nbsp;</span><a href="https://www.cnblogs.com/yixuanhan/p/12593724.html#autoid-1-0-0" title="在本地运行示例 ASP.NET Core JWT身份验证API">在本地运行示例 ASP.NET Core...</a><span class="sideCatalog-dot"></span></li><li><span>3&nbsp;&nbsp;</span><a href="https://www.cnblogs.com/yixuanhan/p/12593724.html#autoid-2-0-0" title="使用Postman测试ASP.NET Core API">使用Postman测试ASP.NET C...</a><span class="sideCatalog-dot"></span></li><li><span>4&nbsp;&nbsp;</span><a href="https://www.cnblogs.com/yixuanhan/p/12593724.html#autoid-3-0-0" title="ASP.NET Core JWT API项目结构">ASP.NET Core JWT API...</a><span class="sideCatalog-dot"></span></li><li class="h3Offset"><span>4.0.1&nbsp;&nbsp;</span><a href="https://www.cnblogs.com/yixuanhan/p/12593724.html#autoid-4-0-0" title="/Controllers/UserController.cs">/Controllers/UserController.cs</a></li><li class="h3Offset"><span>4.0.2&nbsp;&nbsp;</span><a href="https://www.cnblogs.com/yixuanhan/p/12593724.html#autoid-4-0-1" title="/Entities/User.cs">/Entities/User.cs</a></li><li class="h3Offset"><span>4.0.3&nbsp;&nbsp;</span><a href="https://www.cnblogs.com/yixuanhan/p/12593724.html#autoid-4-0-2" title=" /Helper/AppSettings.cs">&nbsp;/Helper/AppSettings.cs</a></li><li class="h3Offset"><span>4.0.4&nbsp;&nbsp;</span><a href="https://www.cnblogs.com/yixuanhan/p/12593724.html#autoid-4-0-3" title=" /Helpers/ExtensionMethods.cs">&nbsp;/Helpers/ExtensionMethods.cs</a></li><li class="h3Offset"><span>4.0.5&nbsp;&nbsp;</span><a href="https://www.cnblogs.com/yixuanhan/p/12593724.html#autoid-4-0-4" title="/Models/AuthenticateModel.cs">/Models/AuthenticateModel.cs</a></li><li class="h3Offset"><span>4.0.6&nbsp;&nbsp;</span><a href="https://www.cnblogs.com/yixuanhan/p/12593724.html#autoid-4-0-5" title="/IServices/IUserService.cs">/IServices/IUserService.cs</a></li><li class="h3Offset"><span>4.0.7&nbsp;&nbsp;</span><a href="https://www.cnblogs.com/yixuanhan/p/12593724.html#autoid-4-0-6" title="/Services/UserService.cs">/Services/UserService.cs</a></li><li class="h3Offset"><span>4.0.8&nbsp;&nbsp;</span><a href="https://www.cnblogs.com/yixuanhan/p/12593724.html#autoid-4-0-7" title="/appsettings.Development.json">/appsettings.Development.json</a></li><li class="h3Offset"><span>4.0.9&nbsp;&nbsp;</span><a href="https://www.cnblogs.com/yixuanhan/p/12593724.html#autoid-4-0-8" title=" /appsettings.json">&nbsp;/appsettings.json</a></li><li class="h3Offset"><span>4.0.10&nbsp;&nbsp;</span><a href="https://www.cnblogs.com/yixuanhan/p/12593724.html#autoid-4-0-9" title="/Program.cs">/Program.cs</a></li><li class="h3Offset"><span>4.0.11&nbsp;&nbsp;</span><a href="https://www.cnblogs.com/yixuanhan/p/12593724.html#autoid-4-0-10" title="/Startup.cs">/Startup.cs</a></li><li class="h3Offset"><span>4.0.12&nbsp;&nbsp;</span><a href="https://www.cnblogs.com/yixuanhan/p/12593724.html#autoid-4-0-11" title=" /JwtAuthDemo.csproj">&nbsp;/JwtAuthDemo.csproj</a></li></ul></div></div><a href="javascript:void(0);" id="sideCatalogBtn" class="sideCatalogBtnDisable"></a></div><script type="text/javascript">getFollowStatus('8304ac90-5228-e411-b908-9dcfd8948a71');</script></body></html>